package controllers

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"supershare/backend/middleware"
	"supershare/backend/models"
	"supershare/backend/utils"
	"time"

	"github.com/beego/beego/v2/client/orm"
	"github.com/beego/beego/v2/core/logs"
	"github.com/beego/beego/v2/server/web"
	"github.com/golang-jwt/jwt/v5"
)

// MiniUserController 小程序用户控制器
type MiniUserController struct {
	web.Controller
}

// PhoneNumberEncryptedData 微信加密的手机号信息
type PhoneNumberEncryptedData struct {
	EncryptedData string `json:"encryptedData"`
	Iv            string `json:"iv"`
	Code          string `json:"code"`
}

// 返回的OpenID和SessionKey
type WxLoginResponse struct {
	OpenID     string `json:"openid"`
	SessionKey string `json:"session_key"`
	UnionID    string `json:"unionid"`
	ErrCode    int    `json:"errcode"`
	ErrMsg     string `json:"errmsg"`
}

// 获取OpenID
func (c *MiniUserController) GetOpenid() {
	// 解析参数
	var params struct {
		Code  string `json:"code"`
		AppID string `json:"app_id"`
	}

	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &params); err != nil {
		c.Data["json"] = utils.ResponseFail("参数错误: " + err.Error())
		c.ServeJSON()
		return
	}

	// 验证code参数
	if params.Code == "" {
		c.Data["json"] = utils.ResponseFail("缺少code参数")
		c.ServeJSON()
		return
	}

	// 获取小程序配置
	config, err := models.GetMiniprogramConfig(params.AppID)
	if err != nil {
		logs.Error("获取小程序配置失败: ", err)
		c.Data["json"] = utils.ResponseFail("系统错误, 无法获取小程序配置")
		c.ServeJSON()
		return
	}

	// 调用微信接口获取openid
	wxLoginData, err := getWxOpenIDAndSessionKey(params.Code, config.AppID, config.AppSecret)
	if err != nil {
		logs.Error("获取微信openid失败: ", err)
		c.Data["json"] = utils.ResponseFail("获取微信openid失败: " + err.Error())
		c.ServeJSON()
		return
	}

	// 返回openid
	c.Data["json"] = utils.ResponseSuccess("获取成功", map[string]interface{}{
		"openid": wxLoginData.OpenID,
	})
	c.ServeJSON()
}

// 检查用户是否存在
func (c *MiniUserController) CheckUserExist() {
	// 获取openid参数
	openid := c.GetString("openid")
	if openid == "" {
		c.Data["json"] = utils.ResponseFail("缺少openid参数")
		c.ServeJSON()
		return
	}

	// 查询会员
	member, err := models.GetMemberByOpenId(openid, 0)

	// 检查是否存在
	if err != nil {
		if err == orm.ErrNoRows {
			// 会员不存在
			c.Data["json"] = utils.ResponseSuccess("用户不存在", map[string]interface{}{
				"exists": false,
			})
			c.ServeJSON()
			return
		}

		logs.Error("查询用户失败: ", err)
		c.Data["json"] = utils.ResponseFail("查询用户失败: " + err.Error())
		c.ServeJSON()
		return
	}

	// 检查是否有手机号(是否已授权)
	if member.Phone == "" {
		c.Data["json"] = utils.ResponseSuccess("用户存在但未授权手机号", map[string]interface{}{
			"exists": false,
		})
		c.ServeJSON()
		return
	}

	// 生成token
	token, err := generateUserToken(member.Id, member.FranchiseId, member.OpenId)
	if err != nil {
		logs.Error("生成token失败: ", err)
		c.Data["json"] = utils.ResponseFail("生成token失败: " + err.Error())
		c.ServeJSON()
		return
	}

	// 更新用户登录信息
	member.LastLoginAt = time.Now().Unix()
	member.LastLoginIp = c.Ctx.Input.IP()
	_, err = orm.NewOrm().Update(member, "LastLoginAt", "LastLoginIp", "UpdatedAt")
	if err != nil {
		logs.Error("更新用户登录信息失败: ", err)
	}

	// 返回用户信息
	c.Data["json"] = utils.ResponseSuccess("用户存在", map[string]interface{}{
		"exists": true,
		"token":  token,
		"userInfo": map[string]interface{}{
			"id":       member.Id,
			"nickname": member.Name,
			"avatar":   member.Avatar,
			"phone":    member.Phone,
			"gender":   member.Gender,
		},
		"openid": member.OpenId,
	})
	c.ServeJSON()
}

// 使用手机号登录或注册
func (c *MiniUserController) LoginOrRegister() {
	// 解析参数
	var params struct {
		AppId         string                 `json:"app_id"`
		OpenId        string                 `json:"openid"`
		Code          string                 `json:"code"`
		EncryptedData string                 `json:"encryptedData"`
		Iv            string                 `json:"iv"`
		UserInfo      map[string]interface{} `json:"userInfo"`
	}

	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &params); err != nil {
		c.Data["json"] = utils.ResponseFail("参数错误: " + err.Error())
		c.ServeJSON()
		return
	}

	// 验证参数
	if params.AppId == "" || params.OpenId == "" || params.Code == "" || params.EncryptedData == "" || params.Iv == "" {
		missingParams := []string{}
		if params.OpenId == "" {
			missingParams = append(missingParams, "app_id")
		}
		if params.OpenId == "" {
			missingParams = append(missingParams, "openid")
		}
		if params.Code == "" {
			missingParams = append(missingParams, "code")
		}
		if params.EncryptedData == "" {
			missingParams = append(missingParams, "encryptedData")
		}
		if params.Iv == "" {
			missingParams = append(missingParams, "iv")
		}

		logs.Warning("登录参数不完整: %v", missingParams)
		c.Data["json"] = utils.ResponseFail(fmt.Sprintf("参数不完整: %s", strings.Join(missingParams, ", ")))
		c.ServeJSON()
		return
	}

	// 获取小程序配置
	config, err := models.GetMiniprogramConfig(params.AppId)
	if err != nil {
		logs.Error("获取小程序配置失败: ", err)
		c.Data["json"] = utils.ResponseFail("系统错误, 无法获取小程序配置")
		c.ServeJSON()
		return
	}

	// 调用微信接口获取session_key
	wxLoginData, err := getWxOpenIDAndSessionKey(params.Code, config.AppID, config.AppSecret)
	if err != nil {
		logs.Error("获取微信session_key失败: ", err)
		c.Data["json"] = utils.ResponseFail("获取微信session_key失败: " + err.Error())
		c.ServeJSON()
		return
	}

	// 记录关键信息便于调试
	logs.Debug("获取到的OpenID: %s, SessionKey长度: %d",
		wxLoginData.OpenID, len(wxLoginData.SessionKey))

	// 解密手机号
	logs.Info("开始解密手机号，EncryptedData长度: %d, Iv长度: %d",
		len(params.EncryptedData), len(params.Iv))

	phoneInfo, err := decryptWXData(params.EncryptedData, params.Iv, wxLoginData.SessionKey)
	if err != nil {
		logs.Error("解密手机号失败: %v", err)

		// 尝试补充可能的错误原因
		errMsg := "解密手机号失败: " + err.Error()

		if strings.Contains(err.Error(), "解密后数据无效") ||
			strings.Contains(err.Error(), "填充无效") {
			errMsg += "，请重新登录获取手机号"
			// 可能是session_key已过期，建议前端重新登录
		}

		c.Data["json"] = utils.ResponseFail(errMsg)
		c.ServeJSON()
		return
	}

	// 验证解密后的数据是否为有效的JSON
	if !json.Valid([]byte(phoneInfo)) {
		logs.Error("解密后数据不是有效的JSON: %s", phoneInfo)
		c.Data["json"] = utils.ResponseFail("解密后数据格式错误，请重新登录")
		c.ServeJSON()
		return
	}

	// 解析手机号
	var phoneData struct {
		PhoneNumber string `json:"phoneNumber"`
	}
	if err := json.Unmarshal([]byte(phoneInfo), &phoneData); err != nil {
		logs.Error("解析手机号失败: ", err)
		c.Data["json"] = utils.ResponseFail("解析手机号失败: " + err.Error())
		c.ServeJSON()
		return
	}

	// 查询会员
	var member *models.Member
	o := orm.NewOrm()

	// 先根据openid查询
	member, _ = models.GetMemberByOpenId(params.OpenId, 0) // 传入0表示不限制加盟商

	if member == nil || member.Id == 0 {
		// 再根据手机号查询
		member, _ = models.GetMemberByPhone(phoneData.PhoneNumber, 0) // 传入0表示不限制加盟商
	}

	// 开始事务
	tx, _ := o.Begin()

	// 用户不存在，创建新用户
	isNewUser := false
	if member == nil || member.Id == 0 {
		isNewUser = true
		member = &models.Member{
			OpenId:      params.OpenId,
			Phone:       phoneData.PhoneNumber,
			RegisterIp:  c.Ctx.Input.IP(),
			Status:      1,
			LastLoginAt: time.Now().Unix(),
			LastLoginIp: c.Ctx.Input.IP(),
		}

		// 设置用户名
		nickname := "用户"
		if len(phoneData.PhoneNumber) > 4 {
			nickname += phoneData.PhoneNumber[len(phoneData.PhoneNumber)-4:]
		}
		member.Name = nickname

		// 设置默认头像
		if avatar, ok := params.UserInfo["avatarUrl"].(string); ok && avatar != "" {
			member.Avatar = avatar
		} else {
			member.Avatar = "/static/images/default_avatar.png"
		}

		// 从用户信息中获取性别
		if gender, ok := params.UserInfo["gender"].(float64); ok {
			member.Gender = int8(gender)
		}

		// 生成会员编号
		member.MemberNo = generateMemberNo()

		// 插入会员
		id, err := o.Insert(member)
		if err != nil {
			tx.Rollback()
			logs.Error("创建会员失败: ", err)
			c.Data["json"] = utils.ResponseFail("创建会员失败: " + err.Error())
			c.ServeJSON()
			return
		}
		member.Id = id
	} else {
		// 用户存在，更新信息
		member.OpenId = params.OpenId
		member.LastLoginAt = time.Now().Unix()
		member.LastLoginIp = c.Ctx.Input.IP()
		member.Phone = phoneData.PhoneNumber

		// 更新头像（如果有）
		if avatar, ok := params.UserInfo["avatarUrl"].(string); ok && avatar != "" {
			member.Avatar = avatar
		}

		// 更新性别（如果有）
		if gender, ok := params.UserInfo["gender"].(float64); ok {
			member.Gender = int8(gender)
		}

		_, err := o.Update(member)
		if err != nil {
			tx.Rollback()
			logs.Error("更新会员信息失败: ", err)
			c.Data["json"] = utils.ResponseFail("更新会员信息失败: " + err.Error())
			c.ServeJSON()
			return
		}
	}

	// 提交事务
	tx.Commit()

	// 生成token
	token, err := generateUserToken(member.Id, member.FranchiseId, member.OpenId)
	if err != nil {
		logs.Error("生成token失败: ", err)
		c.Data["json"] = utils.ResponseFail("生成token失败: " + err.Error())
		c.ServeJSON()
		return
	}

	// 返回用户信息
	c.Data["json"] = utils.ResponseSuccess("登录成功", map[string]interface{}{
		"token": token,
		"userInfo": map[string]interface{}{
			"id":       member.Id,
			"nickname": member.Name,
			"avatar":   member.Avatar,
			"phone":    member.Phone,
			"gender":   member.Gender,
		},
		"openid":    member.OpenId,
		"isNewUser": isNewUser,
	})
	c.ServeJSON()
}

// 使用短信验证码登录
func (c *MiniUserController) LoginWithCode() {
	// 解析参数
	var params struct {
		AppId  string `json:"app_id"`
		Phone  string `json:"phone"`
		Code   string `json:"code"`
		WxCode string `json:"wxCode"`
	}

	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &params); err != nil {
		c.Data["json"] = utils.ResponseFail("参数错误: " + err.Error())
		c.ServeJSON()
		return
	}

	// 验证参数
	if params.Phone == "" || params.Code == "" {
		c.Data["json"] = utils.ResponseFail("手机号和验证码不能为空")
		c.ServeJSON()
		return
	}

	// TODO: 验证验证码
	// 此处简化处理，实际项目中需要验证验证码是否正确

	// 获取OpenID
	var openid string
	if params.WxCode != "" {
		// 获取小程序配置
		config, err := models.GetMiniprogramConfig(params.AppId)
		if err != nil {
			logs.Error("获取小程序配置失败: ", err)
			c.Data["json"] = utils.ResponseFail("系统错误, 无法获取小程序配置")
			c.ServeJSON()
			return
		}

		// 调用微信接口获取openid
		wxLoginData, err := getWxOpenIDAndSessionKey(params.WxCode, config.AppID, config.AppSecret)
		if err != nil {
			logs.Error("获取微信openid失败: ", err)
			c.Data["json"] = utils.ResponseFail("获取微信openid失败: " + err.Error())
			c.ServeJSON()
			return
		}

		openid = wxLoginData.OpenID
	}

	// 查询会员
	member, err := models.GetMemberByPhone(params.Phone, 0) // 传入0表示不限制加盟商
	o := orm.NewOrm()
	isNewUser := false

	if err != nil {
		if err == orm.ErrNoRows {
			// 用户不存在，创建新用户
			isNewUser = true
			member = &models.Member{
				Phone:       params.Phone,
				OpenId:      openid,
				RegisterIp:  c.Ctx.Input.IP(),
				Status:      1,
				LastLoginAt: time.Now().Unix(),
				LastLoginIp: c.Ctx.Input.IP(),
				Name:        "用户" + params.Phone[len(params.Phone)-4:],
				Avatar:      "/static/images/default_avatar.png",
				MemberNo:    generateMemberNo(),
			}

			// 插入会员
			id, err := o.Insert(member)
			if err != nil {
				logs.Error("创建会员失败: ", err)
				c.Data["json"] = utils.ResponseFail("创建会员失败: " + err.Error())
				c.ServeJSON()
				return
			}
			member.Id = id
		} else {
			logs.Error("查询会员失败: ", err)
			c.Data["json"] = utils.ResponseFail("查询会员失败: " + err.Error())
			c.ServeJSON()
			return
		}
	} else {
		// 用户存在，更新登录信息和OpenID
		member.LastLoginAt = time.Now().Unix()
		member.LastLoginIp = c.Ctx.Input.IP()

		if openid != "" && member.OpenId == "" {
			member.OpenId = openid
		}

		_, err := o.Update(member, "LastLoginAt", "LastLoginIp", "OpenId", "UpdatedAt")
		if err != nil {
			logs.Error("更新会员信息失败: ", err)
			c.Data["json"] = utils.ResponseFail("更新会员信息失败: " + err.Error())
			c.ServeJSON()
			return
		}
	}

	// 生成token
	token, err := generateUserToken(member.Id, member.FranchiseId, member.OpenId)
	if err != nil {
		logs.Error("生成token失败: ", err)
		c.Data["json"] = utils.ResponseFail("生成token失败: " + err.Error())
		c.ServeJSON()
		return
	}

	// 返回用户信息
	c.Data["json"] = utils.ResponseSuccess("登录成功", map[string]interface{}{
		"token": token,
		"userInfo": map[string]interface{}{
			"id":       member.Id,
			"nickname": member.Name,
			"avatar":   member.Avatar,
			"phone":    member.Phone,
			"gender":   member.Gender,
		},
		"openid":    member.OpenId,
		"isNewUser": isNewUser,
	})
	c.ServeJSON()
}

// 发送验证码
func (c *MiniUserController) SendVerifyCode() {
	// 解析参数
	var params struct {
		Phone string `json:"phone"`
	}

	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &params); err != nil {
		c.Data["json"] = utils.ResponseFail("参数错误: " + err.Error())
		c.ServeJSON()
		return
	}

	// 验证参数
	if params.Phone == "" {
		c.Data["json"] = utils.ResponseFail("手机号不能为空")
		c.ServeJSON()
		return
	}

	// TODO: 调用短信接口发送验证码
	// 此处简化处理，实际项目中需要调用短信接口发送验证码

	// 返回成功
	c.Data["json"] = utils.ResponseSuccess("验证码已发送", nil)
	c.ServeJSON()
}

// GetUserInfo 获取用户信息
func (c *MiniUserController) GetUserInfo() {
	user, _ := middleware.GetCurrentMember(c.Ctx)
	if user == nil {
		c.Data["json"] = utils.ResponseFail("认证已过期")
		c.ServeJSON()
		return
	}

	// 从上下文获取用户信息
	memberId := c.Ctx.Input.GetData("user_id").(int64)
	franchiseId := c.Ctx.Input.GetData("franchise_id").(int64)

	// 查询会员
	member, err := models.GetMemberById(memberId, franchiseId)
	if err != nil {
		logs.Error("查询会员失败: ", err)
		c.Data["json"] = utils.ResponseFail("查询会员失败: " + err.Error())
		c.ServeJSON()
		return
	}

	// 返回用户信息
	c.Data["json"] = utils.ResponseSuccess("获取成功", map[string]interface{}{
		"id":       member.Id,
		"nickname": member.Name,
		"avatar":   member.Avatar,
		"phone":    member.Phone,
		"gender":   member.Gender,
	})
	c.ServeJSON()
}

// 获取账户信息
func (c *MiniUserController) GetAccountInfo() {
	user, _ := middleware.GetCurrentMember(c.Ctx)
	if user == nil {
		c.Data["json"] = utils.ResponseFail("认证已过期")
		c.ServeJSON()
		return
	}
	// 从上下文获取用户信息
	memberId := c.Ctx.Input.GetData("user_id").(int64)

	// 查询会员
	member, err := models.GetMemberById(memberId, user.FranchiseId)
	if err != nil {
		logs.Error("查询会员失败: ", err)
		c.Data["json"] = utils.ResponseFail("查询会员失败: " + err.Error())
		c.ServeJSON()
		return
	}

	// 获取用户等级
	level, err := models.GetMemberLevelById(member.LevelId, member.FranchiseId)
	if err != nil {
		logs.Error("获取用户等级失败: ", err)
		c.Data["json"] = utils.ResponseFail("获取用户等级失败")
		c.ServeJSON()
		return
	}

	// 查询优惠券数量 - 获取可用优惠券数量（状态为0表示未使用的优惠券）
	issues, err := models.GetMemberCoupons(member.Id, 0)
	couponCount := len(issues)
	if err != nil {
		logs.Error("获取优惠券数量失败: ", err)
		couponCount = 0
	}

	// 查询团购券数量 - 获取已支付的团购订单
	o := orm.NewOrm()
	groupBuyCount, err := o.QueryTable(new(models.GroupBuyOrder)).
		Filter("user_id", member.Id).
		Filter("status", 3). // 已支付状态
		Filter("is_deleted", 0).
		Count()
	if err != nil {
		logs.Error("获取团购券数量失败: ", err)
		groupBuyCount = 0
	}

	// 返回账户信息
	c.Data["json"] = utils.ResponseSuccess("获取成功", map[string]interface{}{
		"balance":   member.Balance,
		"points":    member.Points,
		"level":     level.Name,
		"coupons":   couponCount,
		"groupBuys": groupBuyCount,
	})
	c.ServeJSON()
}

// PointsLogs 获取用户积分变动记录
func (c *MiniUserController) PointsLogs() {
	// 获取当前会员信息
	member, err := middleware.GetCurrentMember(c.Ctx)
	if err != nil || member == nil {
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "未授权访问",
		}
		c.ServeJSON()
		return
	}

	// 解析分页参数
	page, _ := c.GetInt("page", 1)
	pageSize, _ := c.GetInt("page_size", 20)

	// 解析过滤条件
	filters := make(map[string]interface{})
	filters["member_id"] = member.Id
	// 确保只查询当前加盟商的数据
	filters["franchise_id"] = member.FranchiseId

	// 判断是筛选收入还是支出
	typeParam := c.GetString("type")
	if typeParam == "income" {
		// 收入，积分为正数
		filters["points_gt"] = 0
	} else if typeParam == "expense" {
		// 支出，积分为负数
		filters["points_lt"] = 0
	}

	// 获取积分变动记录
	pointsLogs, total, err := models.GetPointsLogList(page, pageSize, filters)
	if err != nil {
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "获取积分变动记录失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}

	// 计算总收入和支出
	var totalEarned, totalUsed int
	// 获取所有积分记录进行统计
	allLogs, _, _ := models.GetPointsLogList(1, 1000, map[string]interface{}{
		"member_id":    member.Id,
		"franchise_id": member.FranchiseId,
	})
	for _, log := range allLogs {
		if log.Points > 0 {
			totalEarned += log.Points
		} else {
			totalUsed += -log.Points
		}
	}

	// 返回积分变动记录
	c.Data["json"] = map[string]interface{}{
		"success": true,
		"message": "获取积分变动记录成功",
		"data": map[string]interface{}{
			"list":      pointsLogs,
			"total":     total,
			"page":      page,
			"page_size": pageSize,
			"stats": map[string]interface{}{
				"total_earned": totalEarned,
				"total_used":   totalUsed,
			},
		},
	}
	c.ServeJSON()
}

// GetBalanceLogs 获取余额变动记录
func (c *MiniUserController) GetBalanceLogs() {
	// 获取当前会员信息
	member, err := middleware.GetCurrentMember(c.Ctx)
	if err != nil || member == nil {
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "未授权访问",
		}
		c.ServeJSON()
		return
	}

	// 解析分页参数
	page, _ := c.GetInt("page", 1)
	pageSize, _ := c.GetInt("page_size", 20)

	// 构建过滤条件
	filters := make(map[string]interface{})
	filters["member_id"] = member.Id
	// 确保只查询当前加盟商的数据
	filters["franchise_id"] = member.FranchiseId

	// 获取余额变动记录
	balanceLogs, total, err := models.GetBalanceLogList(page, pageSize, filters)
	if err != nil {
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "获取余额变动记录失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}

	// 格式化返回数据
	type BalanceLogItem struct {
		Id            int64   `json:"id"`
		Time          int64   `json:"time"`
		Amount        float64 `json:"amount"`
		Reason        string  `json:"reason"`
		OrderNo       string  `json:"order_no,omitempty"`
		BeforeBalance float64 `json:"before_balance"`
		AfterBalance  float64 `json:"after_balance"`
		CreatedAt     int64   `json:"created_at"`
	}

	var list []BalanceLogItem
	for _, log := range balanceLogs {
		// 根据类型生成变动原因描述
		reason := ""
		switch log.Type {
		case 1:
			reason = "充值"
		case 2:
			reason = "消费"
		case 3:
			reason = "退款"
		case 4:
			reason = "管理员调整"
		case 5:
			reason = "充值赠送"
		default:
			reason = log.Description
		}

		// 如果有自定义描述，优先使用
		if log.Description != "" {
			reason = log.Description
		}

		item := BalanceLogItem{
			Id:            log.Id,
			Time:          log.CreatedAt,
			Amount:        log.Amount,
			Reason:        reason,
			OrderNo:       log.OrderNo,
			BeforeBalance: log.BeforeBalance,
			AfterBalance:  log.AfterBalance,
			CreatedAt:     log.CreatedAt,
		}

		list = append(list, item)
	}

	c.Data["json"] = map[string]interface{}{
		"success": true,
		"message": "获取余额变动记录成功",
		"data": map[string]interface{}{
			"list":  list,
			"total": total,
			"page":  page,
			"size":  pageSize,
		},
	}
	c.ServeJSON()
}

// 更新用户信息
func (c *MiniUserController) UpdateUserInfo() { // 获取当前会员信息
	user, err := middleware.GetCurrentMember(c.Ctx)
	if err != nil || user == nil {
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "未授权访问",
		}
		c.ServeJSON()
		return
	}
	// 从上下文获取用户信息
	memberId := c.Ctx.Input.GetData("user_id").(int64)

	// 解析参数
	var params struct {
		Nickname string `json:"nickname"`
		Avatar   string `json:"avatar"`
		Gender   int8   `json:"gender"`
	}

	if err := json.Unmarshal(c.Ctx.Input.RequestBody, &params); err != nil {
		c.Data["json"] = utils.ResponseFail("参数错误: " + err.Error())
		c.ServeJSON()
		return
	}

	// 查询会员
	member, err := models.GetMemberById(memberId, user.FranchiseId)
	if err != nil {
		logs.Error("查询会员失败: ", err)
		c.Data["json"] = utils.ResponseFail("查询会员失败: " + err.Error())
		c.ServeJSON()
		return
	}

	// 更新信息
	o := orm.NewOrm()
	fields := make([]string, 0)

	if params.Nickname != "" {
		member.Name = params.Nickname
		fields = append(fields, "Name")
	}

	if params.Avatar != "" {
		member.Avatar = params.Avatar
		fields = append(fields, "Avatar")
	}

	if params.Gender != 0 {
		member.Gender = params.Gender
		fields = append(fields, "Gender")
	}

	if len(fields) > 0 {
		fields = append(fields, "UpdatedAt")
		_, err := o.Update(member, fields...)
		if err != nil {
			logs.Error("更新会员信息失败: ", err)
			c.Data["json"] = utils.ResponseFail("更新会员信息失败: " + err.Error())
			c.ServeJSON()
			return
		}
	}

	// 返回成功
	c.Data["json"] = utils.ResponseSuccess("更新成功", nil)
	c.ServeJSON()
}

// 退出登录
func (c *MiniUserController) Logout() {
	c.Data["json"] = utils.ResponseSuccess("退出成功", nil)
	c.ServeJSON()
}

// GetMyCoupons 获取会员的优惠券列表
func (c *MiniUserController) GetMyCoupons() {
	// 获取当前会员信息
	member, err := middleware.GetCurrentMember(c.Ctx)
	if err != nil || member == nil {
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "未授权访问",
		}
		c.ServeJSON()
		return
	}

	// 获取状态参数，默认获取所有状态
	status, _ := c.GetInt8("status", -1)

	// 获取会员的优惠券列表
	issues, err := models.GetMemberCoupons(member.Id, status)
	if err != nil {
		c.Data["json"] = map[string]interface{}{
			"success": false,
			"message": "获取优惠券失败: " + err.Error(),
		}
		c.ServeJSON()
		return
	}

	// 转换为前端需要的格式
	var result []map[string]interface{}
	for _, issue := range issues {
		// 获取优惠券信息
		coupon, err := models.GetCouponById(issue.CouponId)
		if err != nil {
			continue
		}

		// 组装数据
		item := map[string]interface{}{
			"id":          issue.Id,
			"coupon_id":   coupon.Id,
			"name":        coupon.Name,
			"type":        coupon.Type,
			"amount":      coupon.Value,      // 转换为元
			"min_consume": coupon.MinConsume, // 转换为元
			"valid_from":  issue.ValidFrom,
			"valid_until": issue.ValidUntil,
			"status":      issue.Status,
			"description": coupon.Description,
			"code":        issue.Code,
			"points":      100, // 默认值，实际应当从具体业务获取
			"condition":   fmt.Sprintf("订单金额满%.2f元可用", coupon.MinConsume/100),
			"validMonths": coupon.ValidDays / 30, // 转换为月，如果不足一个月显示为1个月
		}

		result = append(result, item)
	}

	// 返回数据
	c.Data["json"] = map[string]interface{}{
		"success": true,
		"message": "获取优惠券成功",
		"data":    result,
	}
	c.ServeJSON()
}

// 辅助函数: 调用微信接口获取OpenID和SessionKey
func getWxOpenIDAndSessionKey(code, appID, appSecret string) (*WxLoginResponse, error) {
	if code == "" || appID == "" || appSecret == "" {
		return nil, errors.New("参数不完整")
	}

	// 构建请求URL
	url := "https://api.weixin.qq.com/sns/jscode2session?appid=" + appID +
		"&secret=" + appSecret + "&js_code=" + code + "&grant_type=authorization_code"

	// 发起请求
	resp, err := http.Get(url)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	// 读取响应
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}

	// 解析响应
	var wxResp WxLoginResponse
	if err := json.Unmarshal(body, &wxResp); err != nil {
		return nil, err
	}

	// 检查错误
	if wxResp.ErrCode != 0 {
		return nil, errors.New(wxResp.ErrMsg)
	}

	return &wxResp, nil
}

// 辅助函数: 解密微信数据
func decryptWXData(encryptedData, iv, sessionKey string) (string, error) {
	// 记录参数长度，便于调试
	logs.Debug("解密参数长度 - encryptedData: %d, iv: %d, sessionKey: %d",
		len(encryptedData), len(iv), len(sessionKey))

	// 验证输入参数
	if encryptedData == "" || iv == "" || sessionKey == "" {
		return "", errors.New("参数不能为空")
	}

	// Base64解码
	ciphertext, err := base64.StdEncoding.DecodeString(encryptedData)
	if err != nil {
		logs.Error("解码encryptedData失败: %v, 原始数据长度: %d", err, len(encryptedData))
		return "", errors.New("解码encryptedData失败: " + err.Error())
	}

	rawIV, err := base64.StdEncoding.DecodeString(iv)
	if err != nil {
		logs.Error("解码iv失败: %v, 原始数据长度: %d", err, len(iv))
		return "", errors.New("解码iv失败: " + err.Error())
	}

	key, err := base64.StdEncoding.DecodeString(sessionKey)
	if err != nil {
		logs.Error("解码sessionKey失败: %v, 原始数据长度: %d", err, len(sessionKey))
		return "", errors.New("解码sessionKey失败: " + err.Error())
	}

	// 记录解码后数据长度
	logs.Debug("解码后长度 - ciphertext: %d, rawIV: %d, key: %d",
		len(ciphertext), len(rawIV), len(key))

	// 创建解密器
	block, err := aes.NewCipher(key)
	if err != nil {
		logs.Error("创建解密器失败: %v", err)
		return "", errors.New("创建解密器失败: " + err.Error())
	}

	// 确保IV长度正确
	if len(rawIV) != block.BlockSize() {
		logs.Error("IV长度不正确: %d, 需要: %d", len(rawIV), block.BlockSize())
		return "", errors.New("IV长度不正确")
	}

	// 确保数据长度是块大小的倍数
	if len(ciphertext)%block.BlockSize() != 0 {
		logs.Error("加密数据长度不是块大小的倍数: %d % %d = %d",
			len(ciphertext), block.BlockSize(), len(ciphertext)%block.BlockSize())
		return "", errors.New("加密数据长度无效")
	}

	// 解密
	mode := cipher.NewCBCDecrypter(block, rawIV)
	plaintext := make([]byte, len(ciphertext))
	mode.CryptBlocks(plaintext, ciphertext)

	// 记录解密后数据的前20个字节（如果有）用于调试
	previewLen := 20
	if len(plaintext) < previewLen {
		previewLen = len(plaintext)
	}
	logs.Debug("解密后数据预览(前%d字节): %v", previewLen, plaintext[:previewLen])

	// 去除PKCS#7填充
	paddingLen := int(plaintext[len(plaintext)-1])
	if paddingLen < 1 || paddingLen > block.BlockSize() {
		logs.Error("填充无效: paddingLen=%d", paddingLen)
		return "", errors.New("填充无效")
	}

	// 验证所有填充字节
	for i := len(plaintext) - paddingLen; i < len(plaintext); i++ {
		if plaintext[i] != byte(paddingLen) {
			logs.Error("填充验证失败: 位置=%d, 值=%d, 应为=%d", i, plaintext[i], paddingLen)
			return "", errors.New("填充无效")
		}
	}

	plaintext = plaintext[:len(plaintext)-paddingLen]

	// 查找JSON开始位置
	jsonStartPos := -1
	for i := 0; i < len(plaintext); i++ {
		if plaintext[i] == '{' {
			jsonStartPos = i
			break
		}
	}

	if jsonStartPos == -1 {
		logs.Error("找不到JSON开始位置，解密后数据长度: %d", len(plaintext))
		// 记录更多的数据预览以辅助调试
		if len(plaintext) > 0 {
			maxPreview := 50
			if len(plaintext) < maxPreview {
				maxPreview = len(plaintext)
			}
			logs.Error("解密后数据预览: %s", string(plaintext[:maxPreview]))
		}
		return "", errors.New("解密后数据无效，找不到JSON开始位置")
	}

	result := string(plaintext[jsonStartPos:])
	logs.Debug("解密成功，结果长度: %d, 开始: %s", len(result), result[:min(20, len(result))])
	return result, nil
}

// 辅助函数: 取两个数中的较小值
func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}

// 辅助函数: 生成用户令牌
func generateUserToken(userID int64, fID int64, openID string) (string, error) {
	// 创建JWT token
	token := jwt.New(jwt.SigningMethodHS256)
	// 设置payload
	claims := token.Claims.(jwt.MapClaims)
	claims["user_id"] = userID
	claims["franchise_id"] = fID
	claims["openid"] = openID
	claims["exp"] = time.Now().Add(time.Hour * 24 * 7).Unix() // 设置一周有效期

	// 从配置文件获取secret key
	secretKey, err := web.AppConfig.String("jwtkey")
	if err != nil {
		return "", errors.New("获取JWT key失败")
	}

	// 签名token
	tokenString, err := token.SignedString([]byte(secretKey))
	if err != nil {
		return "", err
	}

	return tokenString, nil
}

// 辅助函数: 生成会员编号
func generateMemberNo() string {
	// 生成会员编号: 日期+4位随机数
	date := time.Now().Format("20060102")
	rand := sha256.Sum256([]byte(time.Now().String()))
	randStr := hex.EncodeToString(rand[:])[:4]
	return "M" + date + strings.ToUpper(randStr)
}
